import { DataSource } from "typeorm";
import { getLogger } from "./lib/util.js";

/** 缓存所有的连接 */
const connections = {};

/**
 * 初始化数据库连接
 * @param config 连接配置
 */
export async function connect(config) {
  const globalLogger = getLogger(config.logger) || "advanced-console";
  // 配置连接
  for (const app in config.connections) {
    if (Object.hasOwn(config.connections, app)) {
      const conn = config.connections[app];
      const itemLogger = getLogger(conn.logger) || globalLogger;
      conn.type = conn.type || "mysql";
      conn.logging = itemLogger === false ? false : "all";
      conn.logger = itemLogger === false ? null : itemLogger;
      if (conn.charset == null) {
        conn.charset = "utf8mb4";
      }
      const entities = conn.entities || [];
      for (const entity of entities) {
        entity.__meta = { app };
      }
      // 连接数据库
      const connectSource = new DataSource(conn);
      connectSource.name = app;
      connections[app] = connectSource;

      try {
        await connectSource.initialize();
        if (globalLogger !== false) {
          if (globalLogger.info) {
            globalLogger.info(`connect to ${connectSource.name} success`);
          } else if (globalLogger.log) {
            globalLogger.log(
              "info",
              `connect to ${connectSource.name} success`
            );
          }
        }
      } catch (err) {
        const errorLogger = globalLogger || console;
        if (errorLogger.error) {
          errorLogger.error(err, err.message);
        } else if (errorLogger.log) {
          errorLogger.log("error", err);
        }
      }
    }
  }
}

/**
 * 注册 fastify 应用使用 typeorm 连接 mysql
 * @param app FastifyInstance
 * @param config 数据库连接配置
 */
export function register_fastify(app, config) {
  if (config.logger == null) {
    config.logger = app.log.child({ name: "typeorm-connection" });
  }
  if (config.connections == null) {
    config.connections = {
      default: { ...config },
    };
  }
  // 添加应用退出监听, 释放资源
  app.addHook("onClose", async (instance) => {
    await destroyAll();
  });
  connect(config).then(); // 连接数据库
}

/**
 * 获取数据源
 * @param entityOrAlias 实体类或者连接别名, 不填, 默认: default
 * @returns
 */
export function dataSource(entityOrAlias) {
  let alias = null;
  if (typeof entityOrAlias === "string") {
    alias = entityOrAlias;
  } else if (entityOrAlias != null) {
    const __meta = entityOrAlias.__meta;
    if (__meta != null) {
      alias = __meta.app;
    }
  }
  alias = alias || "default";
  if (!Object.hasOwn(connections, alias)) {
    throw new Error(`source_name_error: ${alias}`);
  }
  return connections[alias];
}

/**
 * 获取Entity Manager
 * @param entityOrAlias 实体类或者连接别名, 不填, 默认: default
 * @returns
 */
export function manager(entityOrAlias) {
  return dataSource(entityOrAlias).manager;
}

/**
 * 断开某个数据库连接
 * @param alias 连接名称
 */
export async function destroy(alias) {
  if (Object.hasOwn(connections, alias)) {
    const source = connections[alias];
    if (source.isInitialized) {
      await source.destroy();
    }
  }
}

/**
 * 断开所有的连接
 */
export async function destroyAll() {
  const queues = [];
  // eslint-disable-next-line
  for (const key in connections) {
    queues.push(destroy(key));
  }
  await Promise.all(queues);
}

export * from "./lib/entity.js";
